﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Web;
using System.Threading;
using System.Text.RegularExpressions;

namespace Sexybeauty.Framework.Common
{
    public class FileMonitor
    {
        #region Property
        public string FilePath { get; set; }
        #endregion

        #region Constructor
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filePath">如果是下载：为文件路径。如果是上传：可以为string.Empty</param>
        public FileMonitor(string filePath)
        {
            FilePath = filePath;
        }
        #endregion

        #region Public
        public bool DownLoad()
        {
            try
            {
                FileStream myFile = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                string _fileName = FilePath.Substring(FilePath.LastIndexOf('\\') + 1);
                BinaryReader br = new BinaryReader(myFile);
                try
                {
                    HttpContext.Current.Response.AddHeader("Accept-Ranges", "bytes");
                    HttpContext.Current.Response.Buffer = false;
                    long fileLength = myFile.Length;
                    long startBytes = 0;

                    double pack = 10240; //10K bytes
                    int sleep = 200;   //每秒5次   即5*10K bytes每秒
                    if (HttpContext.Current.Request.Headers["Range"] != null)
                    {
                        HttpContext.Current.Response.StatusCode = 206;
                        string[] range = HttpContext.Current.Request.Headers["Range"].Split(new char[] { '=', '-' });
                        startBytes = Convert.ToInt64(range[1]);
                    }
                    HttpContext.Current.Response.AddHeader("Content-Length", (fileLength - startBytes).ToString());
                    if (startBytes != 0)
                    {
                        //Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength-1, fileLength));
                    }
                    HttpContext.Current.Response.AddHeader("Connection", "Keep-Alive");
                    HttpContext.Current.Response.ContentType = "application/octet-stream";
                    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(_fileName, System.Text.Encoding.UTF8));

                    br.BaseStream.Seek(startBytes, SeekOrigin.Begin);
                    int maxCount = (int)Math.Floor((fileLength - startBytes) / pack) + 1;

                    for (int i = 0; i < maxCount; i++)
                    {
                        if (HttpContext.Current.Response.IsClientConnected)
                        {
                            HttpContext.Current.Response.BinaryWrite(br.ReadBytes(int.Parse(pack.ToString())));
                            Thread.Sleep(sleep);
                        }
                        else
                        {
                            i = maxCount;
                        }
                    }
                }
                catch
                {
                    return false;
                }
                finally
                {
                    br.Close();

                    myFile.Close();
                }
            }
            catch
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 文件上传
        /// </summary>
        /// <param name="files"></param>
        /// <param name="upload"></param>
        /// <returns></returns>
        public Dictionary<string, UpdateResult> Upload(UploadFileSetting setting, List<UpLoadFileItem> fileCollection)
        {
            Dictionary<string, UpdateResult> result = new Dictionary<string, UpdateResult>();
            HttpPostedFile postFile;
            string fileType = string.Empty;
            string fileName = string.Empty;
            Regex customerName = new Regex("[^\\w]"); //如果是客户端重名名，删除客户端配置的重命名中的特殊字符

            string uploadPath = string.Empty; //需要上传到的路径
            foreach (var item in fileCollection)
            {
                try
                {
                    postFile = item.File;

                    if (postFile != null && postFile.ContentLength < 5242880) //如果存在该上传文件小于5MB
                    {
                        fileName = postFile.FileName;
                        fileType = GetExtendName(fileName).ToLower();
                        if (setting.TypeFilter.Exists(c => c == FileType.All) || setting.TypeFilter.Exists(c => c.ToString() == fileType)) //如果该文件扩展名为合法
                        {
                            uploadPath = setting.BasePath.Replace("\\", "/");
                            uploadPath = uploadPath.EndsWith("/") ? uploadPath : uploadPath + "/";
                            if (!String.IsNullOrEmpty(item.CustomerFileName))
                            {
                                item.CustomerFileName = customerName.Replace(item.CustomerFileName, ""); //如果是客户端重名名，删除客户端配置的重命名中的特殊字符
                                if (!String.IsNullOrEmpty(item.CustomerFileName))
                                {
                                    item.CustomerFileName = item.CustomerFileName.StartsWith("/") ? item.CustomerFileName.Substring(1) : item.CustomerFileName;
                                    if (!System.IO.Directory.Exists(HttpContext.Current.Server.MapPath(uploadPath)))
                                    {
                                        System.IO.Directory.CreateDirectory(HttpContext.Current.Server.MapPath(uploadPath));
                                    }
                                    uploadPath += item.CustomerFileName;
                                }
                                else
                                {
                                    result.Add(fileName, new UpdateResult()
                                    {
                                        IsSuccess = false,
                                        Error = "重命名输入错误，不能包含特殊字符"
                                    }); //上传失败
                                    continue;
                                }
                            }
                            else
                            {
                                if (!System.IO.Directory.Exists(HttpContext.Current.Server.MapPath(uploadPath)))
                                {
                                    System.IO.Directory.CreateDirectory(HttpContext.Current.Server.MapPath(uploadPath));
                                }
                                string name = new FileInfo(fileName).Name;
                                uploadPath += name;
                            }
                            string s = HttpContext.Current.Server.MapPath(uploadPath);
                            s = GetNewName(fileName, item, s);

                            postFile.SaveAs(s);
                            result.Add(item.FileControlName, new UpdateResult()
                            {
                                IsSuccess = true,
                                ServerPath = "/" + s.Replace(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "").Replace("\\", "/")
                            });

                        }
                        else
                        {
                            result.Add(item.FileControlName, new UpdateResult()
                            {
                                IsSuccess = false,
                                Error = "上传文件格式错误"
                            });
                        }
                    }
                    else
                    {
                        result.Add(item.FileControlName, new UpdateResult()
                        {
                            IsSuccess = false,
                            Error = "上传文件必须不大于5MB"
                        }); //上传失败
                    }
                }
                catch
                {
                    result.Add(item.FileControlName, new UpdateResult()
                    {
                        IsSuccess = false,
                        Error = "系统异常，请稍后再试"
                    });
                }
            }
            return result;
        }
        #endregion

        #region Private
        /// <summary>
        /// 返回扩展名
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private string GetExtendName(string filename)
        {
            Regex reg = new Regex(".+\\.(?<ext>\\w+)$");
            Match match = reg.Match(filename);
            if (match.Success)
            {
                var ext = match.Groups["ext"];
                return ext != null ? ext.Value : string.Empty;
            }
            return string.Empty;
        }
        /// <summary>
        /// 如果现在的复制模式为rename模式，则为该文件选择一个未重复的名字
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="item"></param>
        /// <param name="s"></param>
        /// <param name="circle"></param>
        /// <returns></returns>
        private string GetNewName(string fileName, UpLoadFileItem item, string s, int circle = 1)
        {
            if (item.CopyMode == CopyMode.cover)
            {
                return s;
            }
            if (System.IO.File.Exists(s))
            {
                var fileInfo = new FileInfo(fileName);
                string name = fileInfo.Name;
                string newName = string.Empty;
                if (circle == 1) //如果是第一次递归
                {
                    newName = name.Substring(0, name.LastIndexOf('.')) + "(1)" + fileInfo.Extension;
                }
                else
                {
                    newName = name.Substring(0, name.LastIndexOf('(') + 1) + circle + ")" + fileInfo.Extension;
                }
                s = s.Replace(name, newName);
                s = GetNewName(s, item, s, ++circle);
            }
            return s;
        }

        #endregion
    }
    public class UploadFileSetting
    {
        /// <summary>
        /// 上传到的基础路径
        /// </summary>
        public string BasePath { get; set; }
        /// <summary>
        /// 被允许上传的文件格式
        /// </summary>
        public List<FileType> TypeFilter { get; set; }
    }
    public class UpLoadFileItem
    {
        public HttpPostedFile File { get; set; }
        private string customerFileName = string.Empty;
        /// <summary>
        /// 重命名为，如果为空则不重命名
        /// </summary>
        public string CustomerFileName
        {
            get { return this.customerFileName; }
            set { this.customerFileName = value; }
        }
        private CopyMode copyModel = CopyMode.cover;
        /// <summary>
        /// 当该文件出现重名时选择的复制方式,rename:添加_(数字)的形式，cover：覆盖掉原文件
        /// </summary>
        public CopyMode CopyMode
        {
            get { return this.copyModel; }
            set { this.copyModel = value; }
        }

        /// <summary>
        /// 上传控件的名字
        /// </summary>
        public string FileControlName { get; set; }
    }
    public class UpdateResult
    {
        /// <summary>
        /// false：失败，true：成功
        /// </summary>
        public bool IsSuccess { get; set; }
        /// <summary>
        /// 如果失败，提示信息
        /// </summary>
        public string Error { get; set; }
        /// <summary>
        /// 文件在服务器上的路径
        /// </summary>
        public string ServerPath { get; set; }
    }
    public enum CopyMode
    {
        cover, rename
    }
    public enum FileType
    {
        doc, docx, xls, xlsx, ppt, pptx, pdf, txt, jpg, png,
        All
    }
}
